﻿/*
 * Classe base para todos os testes que executam em um thread próprio.
 * 
 * Responsabilidade:
 * Instanciar e lancar um thread em qual o teste executará.
 * O método trabalhador do thread deve reagir à dois eventos, um do GUI
 * e um do controlador da operação envolvida.
 * O trabalho deve ser dividido em unidades de curto tempo de completarão
 * garantido, e dpois cada unidade um wait para o evento do GUI deve ofereçer
 * uma opção de terminação precoce.
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO.Ports;
using System.Windows.Forms;

namespace J_Controle
{
    public abstract class TesteConcorrente : Teste
    {
        public AutoResetEvent[] evParar;  // [0] do GUI, [1] da porta serial

        Thread thTestar;
        Void_String DlgProtocolar;
        Void_Void DlgAnunciarParada;

        internal TesteConcorrente(string prmNome, Void_Void AnunciarParada, Void_String Protocolar)
            : base(prmNome)
        {
            DlgAnunciarParada = AnunciarParada;
            DlgProtocolar = Protocolar;
        }
        public TesteConcorrente() 
            : base() {}
        public override void Iniciar()
        {
            if (thTestar != null)
            {
                MessageBox.Show("Não pode Iniciar um TesteConcorrente duas vezes.");
                return;
            }

            evParar = new AutoResetEvent[2] 
                { 
                    new AutoResetEvent(false), 
                    new AutoResetEvent(false) 
                };
            thTestar = new Thread(Trabalhador);
            thTestar.Start();
        }
        public override void Terminar()
        {
            if (thTestar == null)
            {
                MessageBox.Show("Não pode terminar um TesteConcorrente não iniciado.");
                return;
            }
            evParar[0].Set();
        }

        public virtual void Conectar(ConfigHW prmConfig, SerialPort prmPorta)
        {
        }
        public virtual void Desconectar()
        {
        }
        protected virtual void Trabalhador() 
        {
            // um fake substituindo o trabalho verdadeiro em classes derivadas
            if (DlgProtocolar != null) DlgProtocolar("Trabalho do thread iniciou\r\n");
            WaitHandle.WaitAny(evParar);  
            if (DlgProtocolar != null) DlgProtocolar("Trabalho do thread Terminou\r\n");
            if (DlgAnunciarParada != null) DlgAnunciarParada();
        }
    }
}
